package com.zy.datareceiver.binsess.monitoring.service.impl;

import com.zy.datareceiver.binsess.decode.service.StorageTaskService;
import com.zy.datareceiver.binsess.monitoring.dao.MonitoringPointDao;
import com.zy.datareceiver.binsess.monitoring.entity.MonitoringPoint;
import com.zy.datareceiver.binsess.monitoring.param.dto.BaseIndexDTO;
import com.zy.datareceiver.binsess.monitoring.param.dto.MonitoringStompDTO;
import com.zy.datareceiver.binsess.monitoring.param.index.*;
import com.zy.datareceiver.binsess.monitoring.service.RealMonitorService;
import com.zy.datareceiver.binsess.rabbit.entity.LoopQueue;
import com.zy.datareceiver.binsess.warning.dao.WarningDataDao;
import com.zy.datareceiver.binsess.warning.dao.WarningLevelDao;
import com.zy.datareceiver.binsess.warning.entity.WarningData;
import com.zy.datareceiver.core.cast.CacheDict;
import com.zy.datareceiver.core.cast.ConCast;
import com.zy.datareceiver.core.common.ServerResponse;
import com.zy.datareceiver.core.utils.DateUtil;
import com.zy.datareceiver.core.utils.WeatherUtil;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.time.LocalDate;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Set;


/**
 * Stomp 主推的核心Service
 * */
@Service
public class RealMonitorServiceImpl implements RealMonitorService {
    private static final Logger log = LoggerFactory.getLogger(RealMonitorServiceImpl.class);
    @Autowired
    private MonitoringPointDao monitoringPointDao;
    @Autowired
    private WarningLevelDao warningLevelDao;
    @Autowired
    private WarningDataDao warningDataDao;


    /**首页大屏*/
    @Override
    public ServerResponse getMonitoringIndexCollectData() {
        BaseIndexDTO baseIndexDTO = new BaseIndexDTO();
        setEquipmentTypesDistribution(baseIndexDTO);//有数据
        setWarningStatisticsData(baseIndexDTO);// 邮件，电信统计为空
        setWarningTypesDistributionData(baseIndexDTO);
        setDetectionData(baseIndexDTO);
        baseIndexDTO.setWeather(WeatherUtil.getWeather(ConCast.AddressCode.QingDao));
        return ServerResponse.success(baseIndexDTO);
    }

    /**实时推送数据显示*/
    @Override
    public ServerResponse getMonitoringCollectData(Integer pointId) {
        MonitoringStompDTO dto = new MonitoringStompDTO();
        setPointInfo(pointId,dto);
        setWarningInfo(pointId,dto);
        DetectionData data = getMonitoringData(pointId);
        dto.setDetectionData(data);
        return ServerResponse.success(dto);
    }

    private void setPointInfo(Integer pointId,MonitoringStompDTO monitoringStompDTO) {
        MonitoringPoint monitoringPoint = monitoringPointDao.selectByPrimaryKey(pointId);
        monitoringStompDTO.setMonitoringPoint(monitoringPoint);
    }

    private void setDetectionData(BaseIndexDTO baseIndexDTO) {
        HashMap<Integer,HashMap<String,DetectionData>> detectionData = new HashMap<>();
        Set<Integer> deviceIds = CacheDict.getAllDeviceId();
        for (Integer deviceId:deviceIds) {
            HashMap<String,DetectionData> detectionDataHashMap = new HashMap<>();
            Set<String> pointNames = CacheDict.getPointNamesByDeviceId(deviceId);
            for (String pointName:pointNames) {
                DetectionData detectionData1 = getMonitoringData(CacheDict.getPointIdByName(pointName));
                detectionDataHashMap.put(pointName,detectionData1);
            }
            detectionData.put(deviceId,detectionDataHashMap);
        }
        baseIndexDTO.setDetectionData(detectionData);
    }

    private void setWarningInfo(Integer pointId,MonitoringStompDTO monitoringStompDTO){
        Date startTime = new Date();
        Date endTime = DateUtils.addDays(startTime,-1);
        List<WarningData>  warningDataList = warningDataDao.selectNearData(pointId,startTime,endTime);
        monitoringStompDTO.setWarningDataList(warningDataList);
    }


    /**
     * 获取监测点的实时数据，从内存的循环队列中取出数据，然后拼装成前端需要的形式，
     * 目前遗留的问题：当一开始的时候，数据为空，再此时进行推送的时候大多数数据为null，
     *  解决办法，在项目启动的时候进行初始化，去数据库中进行查询操作，然后再将数据存入内存队列中，即可解决
     * */
    private DetectionData getMonitoringData(Integer pointId){
        if (pointId == null){
            return null;
        }
        String pointName = CacheDict.getPointNameByPointId(pointId);
        Set<String> parameterNameEns = CacheDict.getParameterNameEnsByPointId(pointId);
        if (pointName == null){
            log.error("对应的传感器不存在，传感器编号为 {}",pointId);
            return null;
        }
        HashMap<String,LoopQueue<DeviceData>> loopQueueHashMap = StorageTaskService.pointMap.get(pointName);
        HashMap<String,Double[]> dataValue = new HashMap<>();

        int[] color = new int[ConCast.StompDestination.Capacity];
        String[] time = new String[ConCast.StompDestination.Capacity];
        for (String parameterNameEn:parameterNameEns) {
            if (MapUtils.isNotEmpty(loopQueueHashMap) && loopQueueHashMap.containsKey(parameterNameEn)){
                LoopQueue<DeviceData> loopQueue= loopQueueHashMap.get(parameterNameEn);

                List<DeviceData> deviceData = null;
                if (loopQueue != null) {
                    deviceData = loopQueue.getData(ConCast.StompDestination.Capacity);
                    Double[] data = new Double[ConCast.StompDestination.Capacity];
                    for (int i= 0;i<deviceData.size();i++) {
                        data[i] = Double.parseDouble(deviceData.get(i).getValue());
                        color[i] = Integer.parseInt(deviceData.get(i).getWarnLevel());
                        time[i] =deviceData.get(i).getTime();
                    }
                    dataValue.put(parameterNameEn,data);
                }else{
                    log.info("当前内存中队列无数据，需要从数据库中查询");
                    //TODO
                }

            }else{
                continue;
            }
        }
        DetectionData detectionData = new DetectionData();
        detectionData.setColor(color);
        detectionData.setShijian(time);
        detectionData.setDataValue(dataValue);
        return detectionData;
    }

    /**设备类型分布*/
    private void setEquipmentTypesDistribution(BaseIndexDTO baseIndexDTO){
        CountTail countTail = monitoringPointDao.countByStatus();
        EquipmentTypesDistribution equipment = new EquipmentTypesDistribution();
        equipment.setAbnormalSum(countTail.getCnt0());//异常设备总数
        equipment.setAnconnectedSum(countTail.getCnt0());//未连接
        equipment.setConnectedSum(countTail.getCnt1());//已连接总数
        equipment.setNormalSum(countTail.getCnt1());//正常运行的设备总数
        equipment.setOnLineSum(countTail.getCnt1());//在线总数
        baseIndexDTO.setEquipmentTypesDistribution(equipment);
    }

    /**预警统计信息*/
    private void setWarningStatisticsData(BaseIndexDTO baseIndexDTO){
        WarningStatisticsData warningStatisticsData = new WarningStatisticsData();
        warningStatisticsData.setTime(DateUtil.format(new Date(),DateUtil.PATTERN_YYYY_MM_DD_HHMMSS));
        warningStatisticsData.setWarnSum(warningDataDao.selectCount(new WarningData()));//邮箱，电话总数是null
        warningStatisticsData.setEmailSum(warningDataDao.selectEmailSum());
        warningStatisticsData.setPhoneSum(warningDataDao.selectPhoneSum());

        baseIndexDTO.setWarningStatisticsData(warningStatisticsData);
    }

    /**预警类型分布*/
    private void setWarningTypesDistributionData(BaseIndexDTO baseIndexDTO){
        String startTime = LocalDate.now() + " 00:00:00";
        String endTime = DateUtil.format(new Date(), DateUtil.PATTERN_YYYY_MM_DD_HHMMSS);
        List<WarningTypesDistributionData> list= warningLevelDao.countWarning(startTime,endTime);
        baseIndexDTO.setWarningTypesDistributionData(list);
    }

    @Override
    public ServerResponse getMsg(String a) {
        Assert.notNull(a,"a不能为空");
        return ServerResponse.success();
    }
}
